//-------------------------------------------------------------------
//	Copyright (c) 2013-2014  Zhirnov Andrey
//	This file is part of the "UX OpwnGL Framework" project.
//	See copyright notice in "UX_GL_Framework.h".
//-------------------------------------------------------------------

#include "Sample.h"

/*
=================================================
	constructor
=================================================
*/
	CSampleApplication::CSampleApplication () :
		_time(0.0f), _surfaceScale(1.0f),
		_vsyncEnabled(true), _timerPaused(false)
	{
	}
	
/*
=================================================
	destructor
=================================================
*/
	CSampleApplication::~CSampleApplication ()
	{
	}
	
/*
=================================================
	OnInit
=================================================
*/
	void CSampleApplication::OnInit ()
	{
		const uvec2 dim = Window()->Descriptor().vSize;

		ShaderLoader::Load( _program, "shaders/sample.prg" );

		_texture = new GLTexture2D();
		_texture->Create( gl_tex_iformat::RGBA8, uvec3(dim) );
		_texture->SetSampler( GLSamplerSrc::Default_Bilinear_Clamp() );
		
		_time = 0.0f;
		
		Window()->SetVSync( _vsyncEnabled );
	}
	
/*
=================================================
	OnFree
=================================================
*/
	void CSampleApplication::OnFree ()
	{
		_program	= null;
		_texture	= null;
	}
	
/*
=================================================
	Draw
=================================================
*/
	void CSampleApplication::Draw ()
	{
		const uvec2 dim = Window()->Descriptor().vSize;

		_program->Bind();

		vec2	resolution	= dim.To<vec2>();
		vec2	mouse		= Input()->GetMousePos().To<vec2>() / resolution;
		vec2	aspect		= vec2( resolution.x / resolution.y, 1.0f ) * _surfaceScale;
		vec2	pos			= _surfacePos;

		GL_CALL( glUniform2fv( _program->GetUniform("surfaceSize"), 1, aspect.ptr() ) );
		GL_CALL( glUniform2fv( _program->GetUniform("unSurfacePos"), 1, pos.ptr() ) );

		GL_CALL( glUniform1f( _program->GetUniform("time"), _time ) );
		GL_CALL( glUniform2fv( _program->GetUniform("mouse"), 1, mouse.ptr() ) );
		GL_CALL( glUniform2fv( _program->GetUniform("resolution"), 1, resolution.ptr() ) );

		DrawQuad();
	}
	
/*
=================================================
	Update
=================================================
*/
	void CSampleApplication::Update ()
	{
		const float mouseSens	= 1.0f;
		const float moveScale	= 0.1f;
		const float wheelScale	= -0.1f;

		if ( Input()->IsKeyClick( e_key::ESCAPE ) )
		{
			Window()->Quit();
			return;
		}

		// reload (reset)
		if ( Input()->IsKeyClick( e_key::R ) )
		{
			_surfacePos		= vec2();
			_time			= 0.0f;
			_timerPaused	= false;

			ShaderLoader::Load( _program, "shaders/sample.prg" );
		}
		
		// vsync
		if ( Input()->IsKeyClick( e_key::V ) )
		{
			_vsyncEnabled = not _vsyncEnabled;
			Window()->SetVSync( _vsyncEnabled );
		}
		
		// move surface
		if ( Input()->IsKey( e_key::M_LEFT ) )
		{
			_surfacePos += vec2(-1.0f, 1.0f) * Input()->GetMouseDelta() * mouseSens *
							_surfaceScale / Window()->Descriptor().vSize.To<vec2>();
		}

		// move surface
		{
			fvec2	move;

			move.y += Input()->IsKey( e_key::W );
			move.y -= Input()->IsKey( e_key::S );
			move.x += Input()->IsKey( e_key::D );
			move.x -= Input()->IsKey( e_key::A );

			_surfacePos += move * moveScale;
		}

		// scale surface
		if ( Input()->GetDeltaWheel() != 0 )
		{
			_surfaceScale += Input()->GetDeltaWheel() * wheelScale;
			_surfaceScale = Clamp( _surfaceScale, 0.1f, 10.0f );
		}

		// timer
		if ( Input()->IsKeyClick( e_key::P ) )
		{
			_timerPaused = not _timerPaused;
		}

		if ( not _timerPaused )
			_time += GetUpdateTimeDelta();
	}
	
/*
=================================================
	OnResize
=================================================
*/
	void CSampleApplication::OnResize ()
	{
		SMAN()->Viewport( Window()->Descriptor().vSize.To<ivec2>() );
	}
	
/*
=================================================
	Run
=================================================
*/
	bool CSampleApplication::Run ()
	{
		CSampleApplication	app;

		return
			app._Run( "FractalEditor/data",
					  CWindow::TDescriptor( uvec2(800,600), ivec2(), e_wnd_style::DEF_WINDOWED, 0, false ),
					  GLWindow::TGLDescriptor( e_glinit_flags::DEFAULT_CORE, 32, 24, 0, 8, 4, true, null ) );
	}
